跳到主要内容

Linux 的环境变量

env 环境变量

使用 env 命令可以显示当前的环境变量

$ env
HOSTTYPE=x86_64
LANG=C.UTF-8 # 使用的系统语言
PATH=/..
TERM=xterm-256color
NAME=DESKTOP-MPNCJNL
HOME=/home/alsritter # 代表使用者的主文件夹, ~ 就是读取这个变量
USER=alsritter
LOGNAME=alsritter
SHELL=/bin/zsh # 目前这个环境使用的 SHELL 是什么,默认是 /bin/bash
...

Linux 的重要环境变量

变量名称作用
HOME用户的家目录(即主目录)
SHELL用户在使用的 Shell 解释器名称
HISTSIZE输出的历史命令记录条数
HISTFILESIZE保存的历史命令记录条数
MAIL邮件保存路径
LANG系统语言、语系名称
RANDOM生成一个随机数字
PS1bash解释器的提示符
PATH定义解释器搜索用户执行命令的路径
EDITOR用户默认的文本编辑器

特殊的 $PATH 目录

在讲解 PATH 环境变量之前,首先介绍一下 which 命令,它用于查找某个命令所在的绝对路径。例如:

$ which rm
/bin/rm
$ which rmdir
/bin/rmdir
$ which ls
alias ls='ls --color=auto'

注意,ls 是一个相对特殊的命令,它使用 alias 命令做了别名,也就是说,我们常用的 ls 实际上执行的是 ls --color=auto

通过使用 which 命令,可以查找各个外部命令(和 Shell 内置命令相对)所在的绝对路径。

$ echo $PATH
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/root/bin

PATH 环境变量的内容是由一堆目录组成的,各目录之间用冒号“:”隔开。

# 可以在环境变量文件里面加上这个来设置 PATH 变量
export PATH=$PATH:/home/username/mysql/bin

不同身份使用者默认的 PATH 不同,默认能够随意执行的指令也不同,且本目录(.)最好不要放到PATH当中。

set 常用自定变量介绍 ⭐

bash 不只有环境变量,还有一些与 bash 操作接口有关的变量,以及使用者自己定义的变量存在的。 那么这些变量如何观察呢?这个时候就得要使用 set 这个指令了。

环境变量=全局变量 自定变量=区域变量

set 除了环境变量之外, 还会将其他在 bash 内的变量通通显示出来(就是非环境变量)

$ set
PS1="[\u@\h \w]\$" # 效果:[root@alsritter ~]$
$ # 目前这个 shell 所使用的 PID
? # 刚刚执行完指令的回传值。
OSTYPE=linux-gnu # 主机硬件与核心的等级
HOSTTYPE=x86_64
MACHTYPE=x86_64

修改这些变量也可以使用 export

# 如下修改为开头是 & 符号
export PS1="[\u@\h \w]"&

下面介绍下这些变量

PS1:就是提示字符的设置,例如终端显示 $ 开头,就是通过这个地方设置的,具体的配置项百度

$:这个 $ 符合本身也是个变量,它表示目前这个 Shell 的 PID (Process ID)。

# 如下打印 Shell 的 PID
$ echo $$
29319

?:这个问号表示上个执行指令的回传值,就是 Golang 学习的那个标准输出 0, 1, 2(具体看文件描述符那篇笔记) 一般来说,如果成功的执行该指令, 则会回传一个 0 值,如果执行过程发生错误,就会回传非为 0 的数值来表示错误。

$ echo $SHELL
/bin/bash # 可顺利显示!没有错误!
$ echo $?
0 # 因为没问题,所以回传值为 0

$ 12name=VBird
bash: 12name=VBird: command not found... # 发生错误了!bash 回报有问题
$ echo $?
127 # 因为有问题,回传错误代码(非为 0)
# 错误代码回传值依据软件而有不同,我们可以利用这个代码来搜寻错误的原因!
$ echo $?
0
# 咦!怎么又变成正确了?这是因为 "?" 只与“上一个执行指令”有关,
# 所以,我们上一个指令是执行“ echo $? ”,当然没有错误,所以是 0 没错!

错误代码回传值依据软件而有不同,可以利用这个代码来搜寻错误的原因,就像 HTTP State 那样定义不同的状态码

OSTYPE, HOSTTYPE, MACHTYPE:表示主机硬件与核心的等级, 目前个人计算机的 CPU 主要分为 32/64 位,其中 32 位又可分为 i386, i586, i686,而 64 位则称为 x86_64。

变量的传递 ⭐

谈了 env 与 set 现在知道有所谓的环境变量与自定变量,那么这两者之间有啥差异呢?其实这两者的差异在于 “该变量是否会被子程序所继续引用”

先介绍下子进程的概念:

当你登陆 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,这个程序的识别使用的是一个称为程序识别码,被称为 PID 的就是。 接下来你在这个 bash 下面所下达的任何指令都是由这个 bash 所衍生出来的,那些被下达的指令就被称为子程序了。

如下示意图:

如上所示,我们在原本的 bash 下面执行另一个 bash ,结果操作的环境接口会跑到第二个 bash 去(就是子程序), 那原本的 bash 就会在暂停的情况 (睡着了,就是 sleep)。整个指令运行的环境是实线的部分!若要回到原本的 bash 去, 就只有将第二个 bash 结束掉 (下达 exit 或 logout) 才行。

注意:在 Linux 里面,一个线程实际是一个进程,所以在 Golang 开协程运行子进程,实际上也是这样阻塞的

介绍了这么多,具体表现在如下:

子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定变量,所以在原本 bash 的自定变量在进入了子程序后就会消失不见, 一直到离开子程序并回到原本的父程序后,这个变量才会又出现!

换个角度来想,也就是说,如果能将自定变量变成环境变量的话,那不就可以让该变量值继续存在于子程序了? 没错!此时,那个 export 指令就很有用啦!如想要让该变量内容继续的在子程序中使用,那么就请执行:

$ export 变量名称

变量传递的原理

上面通过 export 把自定变量转成全局变量(环境变量=全局变量 自定变量=区域变量),那为什么环境变量的数据可以被子程序所引用呢?这是因为内存配置的关系

  1. 当启动一个 shell,操作系统会分配一个内存块给 shell 使用,这个内存里面的变量可让子程序取用
  2. 若在父程序利用 export 功能,可以让自定变量的内容写到上述的内存块当中(环境变量);
  3. 当载入另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的内存块导入自己的环境变量区块当中。

通过这样的关系,我们就可以让某些变量在相关的程序之间存在

Linux 环境变量加载顺序

Linux 是以什么样的顺序加载的呢?

特定的加载顺序会导致相同名称的环境变量定义被覆盖或者不生效。

环境变量可以简单的分成用户自定义的环境变量以及系统级别的环境变量。

  • 用户级别环境变量定义文件:~/.bashrc~/.profile(部分系统为:~/.bash_profile
  • 系统级别环境变量定义文件:/etc/bashrc/etc/profile(部分系统为:/etc/bash_profile)、/etc/environment

读取顺序如下:

References

10.2 Shell 的变量功能